home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / compiler / generic / genesis.lisp < prev    next >
Encoding:
Text File  |  1992-05-27  |  59.1 KB  |  1,790 lines

  1. ;;; -*- Package: Lisp -*-
  2. ;;; **********************************************************************
  3. ;;; This code was written as part of the CMU Common Lisp project at
  4. ;;; Carnegie Mellon University, and has been placed in the public domain.
  5. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  6. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  7. ;;;
  8. (ext:file-comment
  9.   "$Header: genesis.lisp,v 1.71.3.1 92/05/26 22:01:34 ram Exp $")
  10. ;;;
  11. ;;; **********************************************************************
  12. ;;;
  13. ;;; $Header: genesis.lisp,v 1.71.3.1 92/05/26 22:01:34 ram Exp $
  14. ;;;
  15. ;;; Core image builder for CMU Common Lisp.
  16. ;;;
  17. ;;; Written by Skef Wholey.  Package hackery courtesy of Rob MacLachlan.
  18. ;;;
  19. ;;; Completely Rewritten by William Lott for MIPS port.
  20. ;;;
  21.  
  22. (in-package "LISP")
  23.  
  24.  
  25.  
  26. ;;;; Representation of descriptors and spaces in the core.
  27.  
  28. (defvar *dynamic* nil)
  29. (defparameter dynamic-space-id 1)
  30.  
  31. (defvar *static* nil)
  32. (defparameter static-space-id 2)
  33.  
  34. (defvar *read-only* nil)
  35. (defparameter read-only-space-id 3)
  36.  
  37. (defmacro round-up (num size)
  38.   "Rounds number up to be an integral multiple of size."
  39.   (let ((size-var (gensym)))
  40.     `(let ((,size-var ,size))
  41.        (* ,size-var (ceiling ,num ,size-var)))))
  42.  
  43.  
  44. (defstruct (space
  45.         (:constructor %make-space (name identifier address sap
  46.                         words-allocated))
  47.         (:print-function %print-space))
  48.   name                  ; Name of this space.
  49.   identifier              ; Space Identifier
  50.   address              ; Word address it will be at when loaded.
  51.   sap                  ; System area pointer for this space.
  52.   words-allocated          ; Number of words currently allocated.
  53.   (free-pointer 0))          ; Word offset of next free word.
  54.  
  55. (defun %print-space (space stream depth)
  56.   (declare (ignore depth))
  57.   (format stream "#<~S space (#x~X), ~S bytes used>"
  58.       (space-name space)
  59.       (ash (space-address space) 2)
  60.       (ash (space-free-pointer space) 2)))
  61.  
  62. (eval-when (compile eval load)
  63.  
  64. (defconstant descriptor-low-bits 16
  65.   "Number of bits in the low half of the descriptor")
  66.  
  67. (defconstant space-alignment (ash 1 descriptor-low-bits)
  68.   "Alignment requirement for spaces in the target.
  69.   Must be at least (ash 1 descriptor-low-bits")
  70.  
  71. (defvar *target-page-size* (system:get-page-size)
  72.   "The page size to use in the build core.  Set before loading genesis to use a
  73.   value different from the current system page size.")
  74.  
  75. ); eval-when
  76.  
  77. (defstruct (descriptor
  78.         (:constructor make-descriptor (high low &optional space offset))
  79.         (:print-function %print-descriptor))
  80.   space                  ; The space is descriptor is allocated in.
  81.   offset              ; The offset (in words) from the start of
  82.                   ;  that space.
  83.   high                  ; The high half of the descriptor.
  84.   low                  ; The low half of the descriptor.
  85.   )
  86.  
  87. (defun %print-descriptor (des stream depth)
  88.   (declare (ignore depth))
  89.   (let ((lowtag (descriptor-lowtag des)))
  90.     (cond ((or (= lowtag vm:even-fixnum-type) (= lowtag vm:odd-fixnum-type))
  91.        (let ((unsigned
  92.           (logior (ash (descriptor-high des)
  93.                    (1+ (- descriptor-low-bits vm:lowtag-bits)))
  94.               (ash (descriptor-low des) (- 1 vm:lowtag-bits)))))
  95.          (if (> unsigned #x1FFFFFFF)
  96.          (format stream "#<fixnum: ~D>"
  97.              (- unsigned #x40000000))
  98.          (format stream "#<fixnum: ~D>" unsigned))))
  99.       ((or (= lowtag vm:other-immediate-0-type)
  100.            (= lowtag vm:other-immediate-1-type))
  101.        (format stream "#<other immediate: #x~X, type #b~8,'0B>"
  102.            (logior (ash (descriptor-high des)
  103.                 (- descriptor-low-bits vm:type-bits))
  104.                (ash (descriptor-low des)
  105.                 (- vm:type-bits)))
  106.            (logand (descriptor-low des) vm:type-mask)))
  107.       (t
  108.        (format stream "#<pointer: #x~X, lowtag #b~3,'0B, ~A space>"
  109.            (logior (ash (descriptor-high des)
  110.                 descriptor-low-bits)
  111.                (logandc2 (descriptor-low des) vm:lowtag-mask))
  112.            lowtag
  113.            (let ((space (descriptor-space des)))
  114.              (if space
  115.              (space-name space)
  116.              "unknown")))))))
  117.  
  118.  
  119. (defun make-space (name identifier address
  120.             &optional (initial-size space-alignment))
  121.   (multiple-value-bind
  122.       (ignore remainder)
  123.       (truncate address space-alignment)
  124.     (declare (ignore ignore))
  125.     (unless (zerop remainder)
  126.       (error "The address #x~X is not aligned on a #x~X boundry."
  127.          address space-alignment)))
  128.   (let ((actual-size (round-up initial-size *target-page-size*)))
  129.     (let ((addr (allocate-system-memory actual-size)))
  130.       (%make-space name identifier
  131.            (ash address (- vm:word-shift)) addr
  132.            (ash actual-size (- vm:word-shift))))))
  133.  
  134. (defun deallocate-space (space)
  135.   (deallocate-system-memory (space-sap space)
  136.                 (* (space-words-allocated space) vm:word-bytes)))
  137.  
  138. (defun allocate-descriptor (space length lowtag)
  139.   "Return a descriptor for a block of LENGTH bytes out of SPACE.  The free
  140.   pointer is boosted as necessary.  If any additional memory is needed, we
  141.   vm_allocate it.  The descriptor returned is a pointer of type LOWTAG."
  142.   (let* ((bytes (round-up length (ash 1 vm:lowtag-bits)))
  143.      (offset (space-free-pointer space))
  144.      (new-free-ptr (+ offset (ash bytes (- vm:word-shift)))))
  145.     (when (> new-free-ptr (space-words-allocated space))
  146.       (do ((size (space-words-allocated space) (* 2 size)))
  147.       ((>= size new-free-ptr)
  148.        (setf (space-sap space)
  149.          (reallocate-system-memory (space-sap space)
  150.                        (ash (space-words-allocated space)
  151.                         vm:word-shift)
  152.                        (ash size vm:word-shift)))
  153.        (setf (space-words-allocated space) size))))
  154.     (setf (space-free-pointer space) new-free-ptr)
  155.     (let ((ptr (+ (space-address space) offset)))
  156.       (make-descriptor (ash ptr (- vm:word-shift descriptor-low-bits))
  157.                (logior (ash (logand ptr
  158.                         (1- (ash 1
  159.                              (- descriptor-low-bits
  160.                             vm:word-shift))))
  161.                     vm:word-shift)
  162.                    lowtag)
  163.                space
  164.                offset))))
  165.  
  166. (defun descriptor-lowtag (des)
  167.   "Return the lowtag bits for DES."
  168.   (logand (descriptor-low des) vm:lowtag-mask))
  169.  
  170. (defun descriptor-sap (des)
  171.   "Return a SAP pointing to the piece of memory DES refers to.  The lowtag
  172.   bits of DES are ignored."
  173.   (let ((space (descriptor-space des)))
  174.     (when (null space)
  175.       (let ((lowtag (descriptor-lowtag des))
  176.         (high (descriptor-high des))
  177.         (low (descriptor-low des)))
  178.     (when (or (eql lowtag vm:function-pointer-type)
  179.           (eql lowtag vm:structure-pointer-type)
  180.           (eql lowtag vm:list-pointer-type)
  181.           (eql lowtag vm:other-pointer-type))
  182.       (dolist (space (list *dynamic* *static* *read-only*)
  183.              (error "Could not find a space for ~S" des))
  184.         ;; This code relies on the fact that spaces are aligned such that
  185.         ;; the descriptor-low-bits low bits are zero.
  186.         (when (and (>= high (ash (space-address space)
  187.                      (- vm:word-shift descriptor-low-bits)))
  188.                (<= high (ash (+ (space-address space)
  189.                     (space-free-pointer space))
  190.                      (- vm:word-shift descriptor-low-bits))))
  191.           (setf (descriptor-space des) space)
  192.           (setf (descriptor-offset des)
  193.             (+ (ash (- high (ash (space-address space)
  194.                      (- vm:word-shift descriptor-low-bits)))
  195.                 (- descriptor-low-bits vm:word-shift))
  196.                (ash (logandc2 low vm:lowtag-mask) (- vm:word-shift))))
  197.           (return)))))
  198.       (setf space (descriptor-space des)))
  199.     (unless space
  200.       (error "~S has no space?" des))
  201.     (int-sap (+ (sap-int (space-sap space))
  202.         (ash (descriptor-offset des) vm:word-shift)))))
  203.  
  204.  
  205. (defun make-random-descriptor (value)
  206.   (make-descriptor (logand (ash value (- descriptor-low-bits))
  207.                (1- (ash 1 (- vm:word-bits descriptor-low-bits))))
  208.            (logand value (1- (ash 1 descriptor-low-bits)))))
  209.  
  210. (defun make-fixnum-descriptor (num)
  211.   (when (>= (integer-length num)
  212.         (1+ (- vm:word-bits vm:lowtag-bits)))
  213.     (error "~D is too big for a fixnum." num))
  214.   (make-random-descriptor (ash num (1- vm:lowtag-bits))))
  215.  
  216. (defun make-other-immediate-descriptor (data type)
  217.   (make-descriptor (ash data (- vm:type-bits descriptor-low-bits))
  218.            (logior (logand (ash data (- descriptor-low-bits
  219.                         vm:type-bits))
  220.                    (1- (ash 1 descriptor-low-bits)))
  221.                type)))
  222.  
  223. (defun make-character-descriptor (data)
  224.   (make-other-immediate-descriptor data vm:base-char-type))
  225.  
  226. (defun descriptor-beyond (des offset type)
  227.   (let* ((low (logior (+ (logandc2 (descriptor-low des) vm:lowtag-mask)
  228.              offset)
  229.               type))
  230.      (high (+ (descriptor-high des)
  231.           (ash low (- descriptor-low-bits)))))
  232.     (make-descriptor high (logand low (1- (ash 1 descriptor-low-bits))))))
  233.  
  234.  
  235. (defun initialize-spaces ()
  236.   (macrolet ((frob (sym name identifier addr)
  237.            `(if ,sym
  238.             (setf (space-free-pointer ,sym) 0)
  239.             (setf ,sym
  240.               (make-space ,name ,identifier ,addr)))))
  241.     (frob *read-only* :read-only read-only-space-id
  242.       vm:target-read-only-space-start)
  243.     (frob *static* :static static-space-id
  244.       vm:target-static-space-start)
  245.     (frob *dynamic* :dynamic dynamic-space-id
  246.       vm:target-dynamic-space-start)))
  247.  
  248.  
  249. ;;;; Random variables and other noise.
  250.  
  251. (defparameter unbound-marker
  252.   (make-other-immediate-descriptor 0 vm:unbound-marker-type)
  253.   "Handle on the trap object.")
  254.  
  255. (defvar *nil-descriptor* nil
  256.   "Handle on Nil.")
  257.  
  258. (defvar *current-init-functions-cons* nil
  259.   "Head of list of functions to be called when the Lisp starts up.")
  260.  
  261. (defvar *in-cold-load* nil
  262.   "Used by normal loader.")
  263.  
  264.  
  265.  
  266. ;;;; Stuff to read and write the core memory.
  267.  
  268. (defun maybe-byte-swap (word)
  269.   (declare (type (unsigned-byte 32) word))
  270.   (assert (= vm:word-bits 32))
  271.   (assert (= vm:byte-bits 8))
  272.   (if (eq (c:backend-byte-order c:*native-backend*)
  273.       (c:backend-byte-order c:*backend*))
  274.       word
  275.       (logior (ash (ldb (byte 8 0) word) 24)
  276.           (ash (ldb (byte 8 8) word) 16)
  277.           (ash (ldb (byte 8 16) word) 8)
  278.           (ldb (byte 8 24) word))))
  279.  
  280. (defun maybe-byte-swap-short (short)
  281.   (declare (type (unsigned-byte 16) short))
  282.   (assert (= vm:word-bits 32))
  283.   (assert (= vm:byte-bits 8))
  284.   (if (eq (c:backend-byte-order c:*native-backend*)
  285.       (c:backend-byte-order c:*backend*))
  286.       short
  287.       (logior (ash (ldb (byte 8 0) short) 8)
  288.           (ldb (byte 8 8) short))))
  289.   
  290.  
  291. (defun write-indexed (address index value)
  292.   "Write VALUE (a descriptor) INDEX words from ADDRESS (also a descriptor)."
  293.   (if (and (null (descriptor-space value))
  294.        (not (null (descriptor-offset value))))
  295.       (note-load-time-value-reference
  296.        (int-sap (+ (logandc2 (descriptor-low address) vm:lowtag-mask)
  297.            (ash (descriptor-high address) descriptor-low-bits)
  298.            (ash index vm:word-shift)))
  299.        value)
  300.       (let ((sap (descriptor-sap address))
  301.         (high (descriptor-high value))
  302.         (low (descriptor-low value)))
  303.     (setf (sap-ref-32 sap (ash index vm:word-shift))
  304.           (maybe-byte-swap (logior (ash high 16) low))))))
  305.  
  306. (defun write-memory (address value)
  307.   "Write VALUE (a descriptor) at ADDRESS (also a descriptor)."
  308.   (write-indexed address 0 value))
  309.  
  310.  
  311. (defun read-indexed (address index)
  312.   "Return the value (as a descriptor) INDEX words from ADDRESS (a descriptor)."
  313.   (let* ((sap (descriptor-sap address))
  314.      (value (maybe-byte-swap (sap-ref-32 sap (ash index vm:word-shift)))))
  315.     (make-random-descriptor value)))
  316.  
  317. (defun read-memory (address)
  318.   "Return the value at ADDRESS (a descriptor)."
  319.   (read-indexed address 0))
  320.  
  321.  
  322. ;;;; Allocating primitive objects.
  323.  
  324. ;;; There are three kinds of blocks of memory in the new type system:
  325. ;;;
  326. ;;;   Boxed objects (cons cells, structures, etc):
  327. ;;; These objects have no header as all slots are descriptors.
  328. ;;;
  329. ;;;   Unboxed objects (bignums):
  330. ;;; A single header words that contains the length.
  331. ;;;
  332. ;;;   Vector objects:
  333. ;;; A header word with the type, a word for the length, plus the data.
  334. ;;;
  335.  
  336. (defun allocate-boxed-object (space length lowtag)
  337.   "Allocate LENGTH words in SPACE and return a new descriptor of type LOWTAG
  338.   pointing to them."
  339.   (allocate-descriptor space (ash length vm:word-shift) lowtag))
  340.  
  341. (defun allocate-unboxed-object (space element-size length type)
  342.   "Allocate LENGTH units of ELEMENT-SIZE bits plus a header word in SPACE and
  343.   return an ``other-pointer'' descriptor to them.  Initialize the header word
  344.   with the resultant length and TYPE."
  345.   (let* ((bytes (/ (* element-size length) vm:byte-bits))
  346.      (des (allocate-descriptor space
  347.                    (+ bytes vm:word-bytes)
  348.                    vm:other-pointer-type)))
  349.     (write-memory des
  350.           (make-other-immediate-descriptor (ash bytes (- vm:word-shift))
  351.                            type))
  352.     des))
  353.  
  354. (defun allocate-vector-object (space element-size length type)
  355.   "Allocate LENGTH units of ELEMENT-SIZE plus a header plus a length slot in
  356.   SPACE and return an ``other-pointer'' descriptor to them.  Initialize the
  357.   header word with TYPE and the length slot with LENGTH."
  358.   (let* ((bytes (/ (* element-size length) vm:byte-bits))
  359.      (des (allocate-descriptor space (+ bytes (* 2 vm:word-bytes))
  360.                    vm:other-pointer-type)))
  361.     (write-memory des (make-other-immediate-descriptor 0 type))
  362.     (write-indexed des vm:vector-length-slot (make-fixnum-descriptor length))
  363.     des))
  364.  
  365.  
  366.  
  367. ;;;; Routines to move simple objects into the core.
  368.  
  369. (defun string-to-core (string &optional (space *dynamic*))
  370.   "Copy string into the CORE and return a descriptor to it."
  371.   ;; Note: We allocate an extra byte and tweek the length back to make sure
  372.   ;; there will be a null at the end of the string to aid in call-out to
  373.   ;; C.
  374.   (let* ((len (length string))
  375.      (des (allocate-vector-object space vm:byte-bits (1+ len)
  376.                       vm:simple-string-type)))
  377.     (write-indexed des vm:vector-length-slot (make-fixnum-descriptor len))
  378.     (copy-to-system-area string (* vm:vector-data-offset vm:word-bits)
  379.              (descriptor-sap des)
  380.              (* vm:vector-data-offset vm:word-bits)
  381.              (* (1+ len) vm:byte-bits))
  382.     des))
  383.  
  384. (defun bignum-to-core (n)
  385.   "Copy the bignum to the core."
  386.   (let* ((words (ceiling (1+ (integer-length n)) vm:word-bits))
  387.      (handle (allocate-unboxed-object *dynamic* vm:word-bits
  388.                       words vm:bignum-type)))
  389.     (declare (fixnum words))
  390.     (do ((index 1 (1+ index))
  391.      (remainder n (ash remainder (- vm:word-bits))))
  392.     ((> index words)
  393.      (unless (zerop (integer-length remainder))
  394.        (warn "Wrote ~D words of ~D, but ~D was left over"
  395.          words n remainder)))
  396.       (let ((word (ldb (byte vm:word-bits 0) remainder)))
  397.     (write-indexed handle index
  398.                (make-descriptor (ash word (- descriptor-low-bits))
  399.                     (ldb (byte descriptor-low-bits 0)
  400.                          word)))))
  401.     handle))
  402.  
  403. (defun number-pair-to-core (first second type)
  404.   "Makes a number pair of TYPE (ratio or complex) and fills it in."
  405.   (let ((des (allocate-unboxed-object *dynamic* vm:word-bits 2 type)))
  406.     (write-indexed des 1 first)
  407.     (write-indexed des 2 second)
  408.     des))
  409.  
  410. (defun float-to-core (num)
  411.   (etypecase num
  412.     (single-float
  413.      (let ((des (allocate-unboxed-object *dynamic* vm:word-bits
  414.                      vm:single-float-size
  415.                      vm:single-float-type)))
  416.        (write-indexed des vm:single-float-value-slot
  417.               (make-random-descriptor (single-float-bits num)))
  418.        des))
  419.     (double-float
  420.      (let ((des (allocate-unboxed-object *dynamic* vm:word-bits
  421.                      vm:double-float-size
  422.                      vm:double-float-type))
  423.        (high-bits (make-random-descriptor (double-float-high-bits num)))
  424.        (low-bits (make-random-descriptor (double-float-low-bits num))))
  425.        (ecase (c:backend-byte-order c:*backend*)
  426.      (:little-endian
  427.       (write-indexed des vm:double-float-value-slot low-bits)
  428.       (write-indexed des (1+ vm:double-float-value-slot) high-bits))
  429.      (:big-endian
  430.       (write-indexed des vm:double-float-value-slot high-bits)
  431.       (write-indexed des (1+ vm:double-float-value-slot) low-bits)))
  432.        des))))
  433.  
  434. (defun number-to-core (number)
  435.   "Copy the given number to the core, or flame out if we can't deal with it."
  436.   (typecase number
  437.     (integer (if (< (integer-length number) 30)
  438.          (make-fixnum-descriptor number)
  439.          (bignum-to-core number)))
  440.     (ratio (number-pair-to-core (number-to-core (numerator number))
  441.                 (number-to-core (denominator number))
  442.                 vm:ratio-type))
  443.     (complex (number-pair-to-core (number-to-core (realpart number))
  444.                   (number-to-core (imagpart number))
  445.                   vm:complex-type))
  446.     (float (float-to-core number))
  447.     (t (error "~S isn't a cold-loadable number at all!" number))))
  448.  
  449. (defun sap-to-core (sap)
  450.   (let ((des (allocate-unboxed-object *dynamic* vm:word-bits
  451.                       vm:sap-size vm:sap-type)))
  452.     (write-indexed des vm:sap-pointer-slot
  453.            (make-random-descriptor (sap-int sap)))
  454.     des))
  455.  
  456. (defun allocate-cons (space car cdr)
  457.   "Allocate a cons cell in SPACE and fill it in with CAR and CDR."
  458.   (let ((dest (allocate-boxed-object space 2 vm:list-pointer-type)))
  459.     (write-memory dest car)
  460.     (write-indexed dest 1 cdr)
  461.     dest))
  462.  
  463. (defmacro cold-push (thing list)
  464.   "Generates code to push the THING onto the given cold load LIST."
  465.   `(setq ,list (allocate-cons *dynamic* ,thing ,list)))
  466.  
  467.  
  468.  
  469. ;;;; Symbol magic.
  470.  
  471. ;;; Allocate-Symbol allocates a symbol and fills its print name cell and
  472. ;;; property list cell.
  473.  
  474. (defvar *cold-symbol-allocation-space* nil)
  475.  
  476. (defun allocate-symbol (name)
  477.   (declare (simple-string name))
  478.   (let ((symbol (allocate-unboxed-object
  479.          (or *cold-symbol-allocation-space* *dynamic*)
  480.          vm:word-bits (1- vm:symbol-size) vm:symbol-header-type)))
  481.     (write-indexed symbol vm:symbol-value-slot unbound-marker)
  482.     (write-indexed symbol vm:symbol-function-slot unbound-marker)
  483.     (write-indexed symbol vm:symbol-raw-function-addr-slot
  484.            (make-random-descriptor
  485.             (ecase (c:backend-fasl-file-implementation c:*backend*)
  486.               ((#.c:pmax-fasl-file-implementation
  487.             #.c:rt-fasl-file-implementation
  488.             #.c:rt-afpa-fasl-file-implementation)
  489.                (lookup-foreign-symbol "undefined_tramp"))
  490.               (#.c:sparc-fasl-file-implementation
  491.                (lookup-foreign-symbol "_undefined_tramp")))))
  492.     (write-indexed symbol vm:symbol-setf-function-slot unbound-marker)
  493.     (write-indexed symbol vm:symbol-plist-slot *nil-descriptor*)
  494.     (write-indexed symbol vm:symbol-name-slot (string-to-core name *dynamic*))
  495.     (write-indexed symbol vm:symbol-package-slot *nil-descriptor*)
  496.     symbol))
  497.  
  498. (defun cold-setq (symbol value)
  499.   (write-indexed symbol vm:symbol-value-slot value))
  500.  
  501. (defun cold-fset (symbol defn)
  502.   (let ((type (logand (descriptor-low (read-memory defn)) vm:type-mask)))
  503.     (write-indexed symbol vm:symbol-function-slot defn)
  504.     (write-indexed symbol vm:symbol-raw-function-addr-slot
  505.            (ecase (c:backend-fasl-file-implementation c:*backend*)
  506.              ((#.c:pmax-fasl-file-implementation
  507.                #.c:rt-fasl-file-implementation
  508.                #.c:rt-afpa-fasl-file-implementation)
  509.               (ecase type
  510.             (#.vm:function-header-type
  511.              (make-random-descriptor
  512.               (+ (ash (descriptor-high defn) descriptor-low-bits)
  513.                  (logandc2 (descriptor-low defn) vm:lowtag-mask)
  514.                  (ash vm:function-header-code-offset
  515.                   vm:word-shift))))
  516.             (#.vm:closure-header-type
  517.              (make-random-descriptor
  518.               (lookup-foreign-symbol "closure_tramp")))))
  519.              (#.c:sparc-fasl-file-implementation
  520.               (ecase type
  521.             (#.vm:function-header-type defn)
  522.             (#.vm:closure-header-type
  523.              (make-random-descriptor
  524.               (lookup-foreign-symbol "_closure_tramp")))))))))
  525.  
  526. ;;; Cold-Put  --  Internal
  527. ;;;
  528. ;;;    Add a property to a symbol in the core.  Assumes it doesn't exist.
  529. ;;;
  530. (defun cold-put (symbol indicator value)
  531.   (write-indexed symbol
  532.          vm:symbol-plist-slot
  533.          (allocate-cons *dynamic*
  534.             indicator
  535.             (allocate-cons *dynamic*
  536.                    value
  537.                    (read-indexed symbol
  538.                          vm:symbol-plist-slot)))))
  539.  
  540. ;;;; Interning.
  541.  
  542. ;;;    In order to avoid having to know about the package format, we
  543. ;;; build a data structure which we stick in *cold-symbols* that
  544. ;;; holds all interned symbols along with info about their packages.
  545. ;;; The data structure is a list of lists in the following format:
  546. ;;;   (<make-package-arglist>
  547. ;;;    <internal-symbols>
  548. ;;;    <external-symbols>
  549. ;;;    <imported-internal-symbols>
  550. ;;;    <imported-external-symbols>
  551. ;;;    <shadowing-symbols>)
  552. ;;;
  553. ;;;    Package manipulation forms are dumped magically by the compiler
  554. ;;; so that we can eval them at Genesis time.  An eval-for-effect fop
  555. ;;; is used, surrounded by fops that switch the fop table to the hot
  556. ;;; fop table and back.
  557. ;;;
  558.  
  559. ;;; An alist from packages to the list of symbols in that package to be
  560. ;;; dumped.
  561.  
  562. (defvar *cold-packages* nil)
  563.  
  564. ;;; Cold-Intern  --  Internal
  565. ;;;
  566. ;;;    Return a handle on an interned symbol.  If necessary allocate
  567. ;;; the symbol and record which package the symbol was referenced in.
  568. ;;; When we allocatethe symbol, make sure we record a reference to
  569. ;;; the symbol in the home package so that the package gets set.
  570. ;;;
  571. (defun cold-intern (symbol &optional (package (symbol-package symbol)))
  572.   (let ((cold-info (get symbol 'cold-info)))
  573.     (unless cold-info
  574.       (cond ((eq (symbol-package symbol) package)
  575.          (let ((handle (allocate-symbol (symbol-name symbol))))
  576.            (when (eq package *keyword-package*)
  577.          (cold-setq handle handle))
  578.            (setq cold-info
  579.              (setf (get symbol 'cold-info) (cons handle nil)))))
  580.         (t
  581.          (cold-intern symbol)
  582.          (setq cold-info (get symbol 'cold-info)))))
  583.     (unless (memq package (cdr cold-info))
  584.       (push package (cdr cold-info))
  585.       (push symbol (cdr (or (assq package *cold-packages*)
  586.                 (car (push (list package) *cold-packages*))))))
  587.     (car cold-info)))
  588.  
  589. ;;; Initialize-Symbols  --  Internal
  590. ;;;
  591. ;;;    Since the initial symbols must be allocated before we can intern
  592. ;;; anything else, we intern those here.  We also set the values of T and Nil.
  593. ;;;
  594. (defun initialize-symbols ()
  595.   "Initilizes the cold load symbol-hacking data structures."
  596.   (do-all-symbols (sym)
  597.     (remprop sym 'cold-info))
  598.   (setq *cold-packages* nil)
  599.   (let ((*cold-symbol-allocation-space* *static*))
  600.     ;; Special case NIL.
  601.     (let ((des (allocate-unboxed-object *static* vm:word-bits
  602.                     vm:symbol-size 0)))
  603.       (setf *nil-descriptor*
  604.         (make-descriptor (descriptor-high des)
  605.                  (+ (descriptor-low des) (* 2 vm:word-bytes)
  606.                     (- vm:list-pointer-type
  607.                    vm:other-pointer-type))))
  608.       (write-indexed des 1
  609.              (make-other-immediate-descriptor 0 vm:symbol-header-type))
  610.       (write-indexed des (1+ vm:symbol-value-slot) *nil-descriptor*)
  611.       (write-indexed des (1+ vm:symbol-function-slot) *nil-descriptor*)
  612.       (write-indexed des (1+ vm:symbol-setf-function-slot) unbound-marker)
  613.       (write-indexed des (1+ vm:symbol-plist-slot) *nil-descriptor*)
  614.       (write-indexed des (1+ vm:symbol-name-slot)
  615.              (string-to-core "NIL" *dynamic*))
  616.       (write-indexed des (1+ vm:symbol-package-slot) *nil-descriptor*)
  617.       (setf (get nil 'cold-info) (cons *nil-descriptor* nil))
  618.       (cold-intern nil))
  619.  
  620.     ;; Intern the others.
  621.     (dolist (symbol vm:static-symbols)
  622.       (let ((des (cold-intern symbol)))
  623.     (unless (= (- (descriptor-low des) (descriptor-low *nil-descriptor*))
  624.            (vm:static-symbol-offset symbol))
  625.       (warn "Offset from ~S to ~S is ~D, not ~D"
  626.         symbol
  627.         nil
  628.         (- (descriptor-low des) (descriptor-low *nil-descriptor*))
  629.         (vm:static-symbol-offset symbol)))))
  630.  
  631.     ;; Establish the value of T.
  632.     (let ((t-symbol (cold-intern t)))
  633.       (cold-setq t-symbol t-symbol)))
  634.  
  635.   (setf *current-init-functions-cons* *nil-descriptor*))
  636.  
  637. ;;; Finish-Symbols  --  Internal
  638. ;;;
  639. ;;;    Establish initial values for magic symbols.
  640. ;;; 
  641. ;;;    Scan over all the symbols referenced in each package in *cold-packages*
  642. ;;; making the apropriate entry in the *initial-symbols* data structure to
  643. ;;; intern the thing.
  644. ;;;
  645. (defun finish-symbols ()
  646.   (macrolet ((frob (symbol value)
  647.            `(cold-setq (cold-intern ',symbol) ,value)))
  648.     (frob *current-catch-block* (make-fixnum-descriptor 0))
  649.     (frob *current-unwind-protect-block* (make-fixnum-descriptor 0))
  650.     (frob *eval-stack-top* (make-fixnum-descriptor 0))
  651.  
  652.     (frob *free-interrupt-context-index* (make-fixnum-descriptor 0))
  653.  
  654.     (let ((res *nil-descriptor*))
  655.       (dolist (cpkg *cold-packages*)
  656.     (let* ((pkg (car cpkg))
  657.            (shadows (package-shadowing-symbols pkg)))
  658.       (let ((internal *nil-descriptor*)
  659.         (external *nil-descriptor*)
  660.         (imported-internal *nil-descriptor*)
  661.         (imported-external *nil-descriptor*)
  662.         (shadowing *nil-descriptor*))
  663.         (dolist (sym (cdr cpkg))
  664.           (let ((handle (car (get sym 'cold-info))))
  665.         (multiple-value-bind (found where)
  666.                      (find-symbol (symbol-name sym) pkg)
  667.           (unless (and where (eq found sym))
  668.             (error "Symbol ~S is not available in ~S." sym pkg))
  669.           (when (memq sym shadows)
  670.             (cold-push handle shadowing))
  671.           (case where
  672.             (:internal
  673.              (if (eq (symbol-package sym) pkg)
  674.              (cold-push handle internal)
  675.              (cold-push handle imported-internal)))
  676.             (:external
  677.              (if (eq (symbol-package sym) pkg)
  678.              (cold-push handle external)
  679.              (cold-push handle imported-external)))))))
  680.         (let ((r *nil-descriptor*))
  681.           (cold-push shadowing r)
  682.           (cold-push imported-external r)
  683.           (cold-push imported-internal r)
  684.           (cold-push external r)
  685.           (cold-push internal r)
  686.           (cold-push (make-make-package-args pkg) r)
  687.           (cold-push r res)))))
  688.       
  689.       (frob *initial-symbols* res)
  690.       (frob *lisp-initialization-functions* *current-init-functions-cons*))
  691.  
  692.     ;; Nothing should be allocated after this.
  693.     ;;
  694.     (frob *read-only-space-free-pointer*
  695.       (allocate-descriptor *read-only* 0 vm:even-fixnum-type))
  696.     (frob *static-space-free-pointer*
  697.       (allocate-descriptor *static* 0 vm:even-fixnum-type))
  698.     (frob *initial-dynamic-space-free-pointer*
  699.       (allocate-descriptor *dynamic* 0 vm:even-fixnum-type))))
  700.  
  701. ;;; Make-Make-Package-Args  --  Internal
  702. ;;;
  703. ;;;    Make a cold list that can be used as the arglist to make-package to
  704. ;;; make a similar package.
  705. ;;;
  706. (defun make-make-package-args (package)
  707.   (let* ((use *nil-descriptor*)
  708.      (nicknames *nil-descriptor*)
  709.      (res *nil-descriptor*))
  710.     (dolist (u (package-use-list package))
  711.       (when (assoc u *cold-packages*)
  712.     (cold-push (string-to-core (package-name u)) use)))
  713.     (dolist (n (package-nicknames package))
  714.       (cold-push (string-to-core n) nicknames))
  715.     (cold-push (number-to-core (truncate (internal-symbol-count package) 0.8)) res)
  716.     (cold-push (cold-intern :internal-symbols) res)
  717.     (cold-push (number-to-core (truncate (external-symbol-count package) 0.8)) res)
  718.     (cold-push (cold-intern :external-symbols) res)
  719.  
  720.     (cold-push nicknames res)
  721.     (cold-push (cold-intern :nicknames) res)
  722.  
  723.     (cold-push use res)
  724.     (cold-push (cold-intern :use) res)
  725.     
  726.     (cold-push (string-to-core (package-name package)) res)
  727.     res))
  728.  
  729.  
  730.  
  731. ;;;; Reading FASL files.
  732.  
  733. (defvar *cold-fop-functions* (replace (make-array 256) fop-functions)
  734.   "FOP functions for cold loading.")
  735.  
  736. (defvar *normal-fop-functions*)
  737.  
  738. ;;; Define-Cold-FOP  --  Internal
  739. ;;;
  740. ;;;    Like Define-FOP in load, but looks up the code, and stores into
  741. ;;; the *cold-fop-functions* vector.
  742. ;;;
  743. (defmacro define-cold-fop ((name &optional (pushp t)) &rest forms)
  744.   (let ((fname (concat-pnames 'cold- name))
  745.     (code (get name 'fop-code)))
  746.     `(progn
  747.        (defun ,fname ()
  748.      ,@(if (eq pushp :nope)
  749.            forms
  750.            `((with-fop-stack ,pushp ,@forms))))
  751.        ,@(if code
  752.          `((setf (svref *cold-fop-functions* ,code) #',fname))
  753.          (warn "~S is not a defined FOP." name)))))
  754.  
  755. ;;; Clone-Cold-FOP  --  Internal
  756. ;;;
  757. ;;;    Clone a couple of cold fops.
  758. ;;;
  759. (defmacro clone-cold-fop ((name &optional (pushp t)) (small-name) &rest forms)
  760.   `(progn
  761.     (macrolet ((clone-arg () '(read-arg 4)))
  762.       (define-cold-fop (,name ,pushp) ,@forms))
  763.     (macrolet ((clone-arg () '(read-arg 1)))
  764.       (define-cold-fop (,small-name ,pushp) ,@forms))))
  765.  
  766. ;;; Not-Cold-Fop  --  Internal
  767. ;;;
  768. ;;;    Define a fop to be undefined in cold load.
  769. ;;;
  770. (defmacro not-cold-fop (name)
  771.   `(define-cold-fop (,name)
  772.      (error "~S is not supported in cold load." ',name)))
  773.  
  774. ;;;; Random cold fops...
  775.  
  776. (define-cold-fop (fop-misc-trap) unbound-marker)
  777.  
  778. (define-cold-fop (fop-character)
  779.   (make-character-descriptor (read-arg 3)))
  780. (define-cold-fop (fop-short-character)
  781.   (make-character-descriptor (read-arg 1)))
  782.  
  783. (define-cold-fop (fop-empty-list) *nil-descriptor*)
  784. (define-cold-fop (fop-truth) (cold-intern t))
  785.  
  786. (define-cold-fop (fop-normal-load :nope)
  787.   (setq fop-functions *normal-fop-functions*))
  788.  
  789. (define-fop (fop-maybe-cold-load 82 :nope)
  790.   (when *in-cold-load*
  791.     (setq fop-functions *cold-fop-functions*)))
  792.  
  793. (define-cold-fop (fop-maybe-cold-load :nope))
  794.  
  795. (clone-cold-fop (fop-struct)
  796.         (fop-small-struct)
  797.   (let* ((size (clone-arg))
  798.      (result (allocate-boxed-object *dynamic* (1+ size)
  799.                     vm:structure-pointer-type)))
  800.     (write-memory result (make-other-immediate-descriptor
  801.               size vm:structure-header-type))
  802.     (do ((index (1- size) (1- index)))
  803.     ((minusp index))
  804.       (declare (fixnum index))
  805.       (write-indexed result (+ index vm:structure-slots-offset) (pop-stack)))
  806.     result))
  807.  
  808.  
  809. ;;; Loading symbols...
  810.  
  811. ;;; Cold-Load-Symbol loads a symbol N characters long from the File and interns
  812. ;;; that symbol in the given Package.
  813. ;;;
  814. (defun cold-load-symbol (size package)
  815.   (let ((string (make-string size)))
  816.     (read-n-bytes *fasl-file* string 0 size)
  817.     (cold-intern (intern string package) package)))
  818.  
  819. (clone-cold-fop (fop-symbol-save)
  820.         (fop-small-symbol-save)
  821.   (push-table (cold-load-symbol (clone-arg) *package*)))
  822.  
  823. (macrolet ((frob (name pname-len package-len)
  824.          `(define-cold-fop (,name)
  825.         (let ((index (read-arg ,package-len)))
  826.           (push-table
  827.            (cold-load-symbol (read-arg ,pname-len)
  828.                      (svref *current-fop-table* index)))))))
  829.   (frob fop-symbol-in-package-save 4 4)
  830.   (frob fop-small-symbol-in-package-save 1 4)
  831.   (frob fop-symbol-in-byte-package-save 4 1)
  832.   (frob fop-small-symbol-in-byte-package-save 1 1))
  833.  
  834. (clone-cold-fop (fop-lisp-symbol-save)
  835.         (fop-lisp-small-symbol-save)
  836.   (push-table (cold-load-symbol (clone-arg) *lisp-package*)))
  837.  
  838. (clone-cold-fop (fop-keyword-symbol-save)
  839.         (fop-keyword-small-symbol-save)
  840.   (push-table (cold-load-symbol (clone-arg) *keyword-package*)))
  841.  
  842. (clone-cold-fop (fop-uninterned-symbol-save)
  843.         (fop-uninterned-small-symbol-save)
  844.   (let* ((size (clone-arg))
  845.      (name (make-string size)))
  846.     (read-n-bytes *fasl-file* name 0 size)
  847.     (let ((symbol (allocate-symbol name)))
  848.       (push-table symbol))))
  849.  
  850. ;;; Loading lists...
  851.  
  852. ;;; Cold-Stack-List makes a list of the top Length things on the Fop-Stack.
  853. ;;; The last cdr of the list is set to Last.
  854.  
  855. (defmacro cold-stack-list (length last)
  856.   `(do* ((index ,length (1- index))
  857.      (result ,last (allocate-cons *dynamic* (pop-stack) result)))
  858.     ((= index 0) result)
  859.      (declare (fixnum index))))
  860.  
  861. (define-cold-fop (fop-list)
  862.   (cold-stack-list (read-arg 1) *nil-descriptor*))
  863. (define-cold-fop (fop-list*)
  864.   (cold-stack-list (read-arg 1) (pop-stack)))
  865. (define-cold-fop (fop-list-1)
  866.   (cold-stack-list 1 *nil-descriptor*))
  867. (define-cold-fop (fop-list-2)
  868.   (cold-stack-list 2 *nil-descriptor*))
  869. (define-cold-fop (fop-list-3)
  870.   (cold-stack-list 3 *nil-descriptor*))
  871. (define-cold-fop (fop-list-4)
  872.   (cold-stack-list 4 *nil-descriptor*))
  873. (define-cold-fop (fop-list-5)
  874.   (cold-stack-list 5 *nil-descriptor*))
  875. (define-cold-fop (fop-list-6)
  876.   (cold-stack-list 6 *nil-descriptor*))
  877. (define-cold-fop (fop-list-7)
  878.   (cold-stack-list 7 *nil-descriptor*))
  879. (define-cold-fop (fop-list-8)
  880.   (cold-stack-list 8 *nil-descriptor*))
  881. (define-cold-fop (fop-list*-1)
  882.   (cold-stack-list 1 (pop-stack)))
  883. (define-cold-fop (fop-list*-2)
  884.   (cold-stack-list 2 (pop-stack)))
  885. (define-cold-fop (fop-list*-3)
  886.   (cold-stack-list 3 (pop-stack)))
  887. (define-cold-fop (fop-list*-4)
  888.   (cold-stack-list 4 (pop-stack)))
  889. (define-cold-fop (fop-list*-5)
  890.   (cold-stack-list 5 (pop-stack)))
  891. (define-cold-fop (fop-list*-6)
  892.   (cold-stack-list 6 (pop-stack)))
  893. (define-cold-fop (fop-list*-7)
  894.   (cold-stack-list 7 (pop-stack)))
  895. (define-cold-fop (fop-list*-8)
  896.   (cold-stack-list 8 (pop-stack)))
  897.  
  898. ;;; Loading vectors...
  899.  
  900. (clone-cold-fop (fop-string)
  901.         (fop-small-string)
  902.   (let* ((len (clone-arg))
  903.      (string (make-string len)))
  904.     (read-n-bytes *fasl-file* string 0 len)
  905.     (string-to-core string)))
  906.  
  907. (clone-cold-fop (fop-vector)
  908.         (fop-small-vector)
  909.   (let* ((size (clone-arg))
  910.      (result (allocate-vector-object *dynamic* vm:word-bits size
  911.                      vm:simple-vector-type)))
  912.     (do ((index (1- size) (1- index)))
  913.     ((minusp index))
  914.       (declare (fixnum index))
  915.       (write-indexed result (+ index vm:vector-data-offset) (pop-stack)))
  916.     result))
  917.  
  918. (clone-cold-fop (fop-uniform-vector)
  919.         (fop-small-uniform-vector)
  920.   (let* ((size (clone-arg))
  921.      (datum (pop-stack))
  922.      (result (allocate-vector-object *dynamic* vm:word-bits size
  923.                      vm:simple-vector-type)))
  924.     (do ((index (1- size) (1- index)))
  925.     ((minusp index))
  926.       (declare (fixnum index))
  927.       (write-indexed result (+ index vm:vector-data-offset) datum))
  928.     result))
  929.  
  930. (define-cold-fop (fop-uniform-int-vector)
  931.   (let* ((len (read-arg 4))
  932.      (size (read-arg 1))
  933.      (type (case size
  934.          (1 vm:simple-bit-vector-type)
  935.          (2 vm:simple-array-unsigned-byte-2-type)
  936.          (4 vm:simple-array-unsigned-byte-4-type)
  937.          (8 vm:simple-array-unsigned-byte-8-type)
  938.          (16 vm:simple-array-unsigned-byte-16-type)
  939.          (32 vm:simple-array-unsigned-byte-32-type)
  940.          (t (error "Losing element size: ~D." size))))
  941.      (value (case size
  942.           ((1 2 4 8)
  943.            (read-arg 1))
  944.           (16
  945.            (read-arg 2))
  946.           (32
  947.            (read-arg 4))))
  948.      (result (allocate-vector-object *dynamic* size len type)))
  949.     (do ((bits size (* bits 2))
  950.      (word value (logior word (ash word bits))))
  951.     ((= size vm:word-bits)
  952.      (let ((datum (make-random-descriptor word)))
  953.        (dotimes (index (ceiling (* len size) vm:word-bits))
  954.          (write-indexed result (+ index vm:vector-data-offset) datum)))))
  955.     result))
  956.  
  957. (define-cold-fop (fop-int-vector)
  958.   (let* ((len (read-arg 4))
  959.      (size (read-arg 1))
  960.      (type (case size
  961.          (1 vm:simple-bit-vector-type)
  962.          (2 vm:simple-array-unsigned-byte-2-type)
  963.          (4 vm:simple-array-unsigned-byte-4-type)
  964.          (8 vm:simple-array-unsigned-byte-8-type)
  965.          (16 vm:simple-array-unsigned-byte-16-type)
  966.          (32 vm:simple-array-unsigned-byte-32-type)
  967.          (t (error "Losing element size: ~D." size))))
  968.      (result (allocate-vector-object *dynamic* size len type)))
  969.     (unless (zerop len)
  970.       (read-n-bytes *fasl-file*
  971.             (descriptor-sap result)
  972.             (ash vm:vector-data-offset vm:word-shift)
  973.             (ceiling (* len size) vm:byte-bits)))
  974.     result))
  975.  
  976. (define-cold-fop (fop-single-float-vector)
  977.   (let* ((len (read-arg 4))
  978.      (result (allocate-vector-object *dynamic* vm:word-bits len
  979.                      vm:simple-array-single-float-type)))
  980.     (unless (zerop len)
  981.       (read-n-bytes *fasl-file*
  982.             (descriptor-sap result)
  983.             (ash vm:vector-data-offset vm:word-shift)
  984.             (* len vm:word-bytes)))
  985.     result))
  986.  
  987. (define-cold-fop (fop-double-float-vector)
  988.   (let* ((len (read-arg 4))
  989.      (result (allocate-vector-object *dynamic* (* vm:word-bits 2) len
  990.                      vm:simple-array-double-float-type)))
  991.     (unless (zerop len)
  992.       (read-n-bytes *fasl-file*
  993.             (descriptor-sap result)
  994.             (ash vm:vector-data-offset vm:word-shift)
  995.             (* len vm:word-bytes 2)))
  996.     result))
  997.  
  998. (define-cold-fop (fop-array)
  999.   (let* ((rank (read-arg 4))
  1000.      (data-vector (pop-stack))
  1001.      (result (allocate-boxed-object *dynamic*
  1002.                     (+ vm:array-dimensions-offset rank)
  1003.                     vm:other-pointer-type)))
  1004.     (write-memory result
  1005.           (make-other-immediate-descriptor rank vm:simple-array-type))
  1006.     (write-indexed result vm:array-fill-pointer-slot *nil-descriptor*)
  1007.     (write-indexed result vm:array-data-slot data-vector)
  1008.     (write-indexed result vm:array-displacement-slot *nil-descriptor*)
  1009.     (write-indexed result vm:array-displaced-p-slot *nil-descriptor*)
  1010.     (let ((total-elements 1))
  1011.       (dotimes (axis rank)
  1012.     (let ((dim (pop-stack)))
  1013.       (unless (or (= (descriptor-lowtag dim) vm:even-fixnum-type)
  1014.               (= (descriptor-lowtag dim) vm:odd-fixnum-type))
  1015.         (error "Non-fixnum dimension? (~S)" dim))
  1016.       (setf total-elements
  1017.         (* total-elements
  1018.            (logior (ash (descriptor-high dim)
  1019.                 (- descriptor-low-bits (1- vm:lowtag-bits)))
  1020.                (ash (descriptor-low dim)
  1021.                 (- 1 vm:lowtag-bits)))))
  1022.       (write-indexed result (+ vm:array-dimensions-offset axis) dim)))
  1023.       (write-indexed result vm:array-elements-slot
  1024.              (make-fixnum-descriptor total-elements)))
  1025.     result))
  1026.  
  1027. ;;; Loading numbers.
  1028.  
  1029. (defmacro cold-number (fop)
  1030.   `(define-cold-fop (,fop :nope)
  1031.      (,fop)
  1032.      (with-fop-stack t
  1033.        (number-to-core (pop-stack)))))
  1034.  
  1035. (cold-number fop-single-float)
  1036. (cold-number fop-double-float)
  1037. (cold-number fop-integer)
  1038. (cold-number fop-small-integer)
  1039. (cold-number fop-word-integer)
  1040. (cold-number fop-byte-integer)
  1041.  
  1042. (define-cold-fop (fop-ratio)
  1043.   (let ((den (pop-stack)))
  1044.     (number-pair-to-core (pop-stack) den vm:ratio-type)))
  1045.  
  1046. (define-cold-fop (fop-complex)
  1047.   (let ((im (pop-stack)))
  1048.     (number-pair-to-core (pop-stack) im vm:complex-type)))
  1049.  
  1050.  
  1051. ;;; Calling (or not calling).
  1052.  
  1053. (not-cold-fop fop-eval)
  1054. (not-cold-fop fop-eval-for-effect)
  1055.  
  1056.  
  1057. (defvar *load-time-value-counter*)
  1058.  
  1059. (define-cold-fop (fop-funcall)
  1060.   (unless (= (read-arg 1) 0)
  1061.     (error "Can't FOP-FUNCALL random stuff in cold load."))
  1062.   (let ((counter *load-time-value-counter*))
  1063.     (cold-push (allocate-cons
  1064.         *dynamic*
  1065.         (cold-intern :load-time-value)
  1066.         (allocate-cons
  1067.          *dynamic*
  1068.          (pop-stack)
  1069.          (allocate-cons
  1070.           *dynamic*
  1071.           (number-to-core counter)
  1072.           *nil-descriptor*)))
  1073.            *current-init-functions-cons*)
  1074.     (setf *load-time-value-counter* (1+ counter))
  1075.     (make-descriptor 0 0 nil counter)))
  1076.  
  1077. (defun note-load-time-value-reference (address marker)
  1078.   (cold-push (allocate-cons
  1079.           *dynamic*
  1080.           (cold-intern :load-time-value-fixup)
  1081.           (allocate-cons
  1082.            *dynamic*
  1083.            (sap-to-core address)
  1084.            (allocate-cons
  1085.         *dynamic*
  1086.         (number-to-core (descriptor-offset marker))
  1087.         *nil-descriptor*)))
  1088.          *current-init-functions-cons*))
  1089.  
  1090. (defun finalize-load-time-value-noise ()
  1091.   (cold-setq (cold-intern 'lisp::*load-time-values*)
  1092.          (allocate-vector-object *dynamic* vm:word-bits
  1093.                      *load-time-value-counter*
  1094.                      vm:simple-vector-type)))
  1095.  
  1096. (define-cold-fop (fop-funcall-for-effect nil)
  1097.   (if (= (read-arg 1) 0)
  1098.       (cold-push (pop-stack) *current-init-functions-cons*)
  1099.       (error "Can't FOP-FUNCALL random stuff in cold load.")))
  1100.  
  1101.  
  1102. ;;;; Fixing up circularities.
  1103.  
  1104. (define-cold-fop (fop-rplaca nil)
  1105.   (let ((obj (svref *current-fop-table* (read-arg 4)))
  1106.     (idx (read-arg 4)))
  1107.     (write-memory (cold-nthcdr idx obj) (pop-stack))))
  1108.  
  1109. (define-cold-fop (fop-rplacd nil)
  1110.   (let ((obj (svref *current-fop-table* (read-arg 4)))
  1111.     (idx (read-arg 4)))
  1112.     (write-indexed (cold-nthcdr idx obj) 1 (pop-stack))))
  1113.  
  1114. (define-cold-fop (fop-svset nil)
  1115.   (let ((obj (svref *current-fop-table* (read-arg 4)))
  1116.     (idx (read-arg 4)))
  1117.     (write-indexed obj
  1118.            (+ idx
  1119.               (ecase (descriptor-lowtag obj)
  1120.             (#.vm:structure-pointer-type 1)
  1121.             (#.vm:other-pointer-type 2)))
  1122.            (pop-stack))))
  1123.  
  1124. (define-cold-fop (fop-structset nil)
  1125.   (let ((obj (svref *current-fop-table* (read-arg 4)))
  1126.     (idx (read-arg 4)))
  1127.     (write-indexed obj (1+ idx) (pop-stack))))
  1128.  
  1129. (define-cold-fop (fop-nthcdr t)
  1130.   (cold-nthcdr (read-arg 4) (pop-stack)))
  1131.  
  1132.  
  1133. (defun cold-nthcdr (index obj)
  1134.   (dotimes (i index)
  1135.     (setq obj (read-indexed obj 1)))
  1136.   obj)
  1137.  
  1138.  
  1139. ;;; Loading code objects and functions.
  1140.  
  1141. (define-cold-fop (fop-fset nil)
  1142.   (let ((fn (pop-stack))
  1143.     (sym (pop-stack)))
  1144.     (cold-fset sym fn)))
  1145.  
  1146. (defun cold-verify-code-format ()
  1147.   (unless *current-code-format*
  1148.     (error "Can't load code until after FOP-CODE-FORMAT."))
  1149.   (let ((implementation (car *current-code-format*))
  1150.     (version (cdr *current-code-format*)))
  1151.     (unless (= implementation (c:backend-fasl-file-implementation c:*backend*))
  1152.       (error
  1153.        "~A was compiled for a ~A, but we are trying to build a core for a ~A"
  1154.        *Fasl-file*
  1155.        (or (elt c:fasl-file-implementations implementation)
  1156.        "unknown machine")
  1157.        (or (elt c:fasl-file-implementations
  1158.         (c:backend-fasl-file-implementation c:*backend*))
  1159.        "unknown machine")))
  1160.     (unless (= version (c:backend-fasl-file-version c:*backend*))
  1161.       (error
  1162.        "~A was compiled for a fasl-file version ~A, but we need version ~A"
  1163.        *Fasl-file* version (c:backend-fasl-file-version c:*backend*)))))
  1164.  
  1165. (defmacro define-cold-code-fop (name nconst size)
  1166.   `(define-cold-fop (,name)
  1167.      (cold-verify-code-format)
  1168.      (let* ((nconst ,nconst)
  1169.         (size ,size)
  1170.         (header-size
  1171.          ;; Note: we round the number of constants up to assure that
  1172.          ;; the code vector will be properly aligned.
  1173.          (round-up (+ vm:code-trace-table-offset-slot nconst) 2))
  1174.         (des (allocate-descriptor *dynamic*
  1175.                       (+ (ash header-size vm:word-shift) size)
  1176.                       vm:other-pointer-type)))
  1177.        (write-memory des
  1178.              (make-other-immediate-descriptor header-size
  1179.                               vm:code-header-type))
  1180.        (write-indexed des vm:code-code-size-slot
  1181.               (make-fixnum-descriptor
  1182.                (ash (+ size (1- (ash 1 vm:word-shift)))
  1183.                 (- vm:word-shift))))
  1184.        (write-indexed des vm:code-entry-points-slot *nil-descriptor*)
  1185.        (write-indexed des vm:code-debug-info-slot (pop-stack))
  1186.        (do ((index (+ nconst (1- vm:code-trace-table-offset-slot))
  1187.            (1- index)))
  1188.        ((< index vm:code-trace-table-offset-slot))
  1189.      (write-indexed des index (pop-stack)))
  1190.        (read-n-bytes *fasl-file*
  1191.              (descriptor-sap des)
  1192.              (ash header-size vm:word-shift)
  1193.              size)
  1194.        des)))  
  1195.  
  1196. (define-cold-code-fop fop-code (read-arg 4) (read-arg 4))
  1197.  
  1198. (define-cold-code-fop fop-small-code (read-arg 1) (read-arg 2))
  1199.  
  1200.  
  1201. (clone-cold-fop (fop-alter-code nil)
  1202.         (fop-byte-alter-code)
  1203.   (let ((slot (clone-arg))
  1204.     (value (pop-stack))
  1205.     (code (pop-stack)))
  1206.     (write-indexed code slot value)))
  1207.  
  1208. (defun calc-offset (code-object after-header)
  1209.   (let ((header (read-memory code-object)))
  1210.     (+ after-header
  1211.        (ash (logior (ash (descriptor-high header)
  1212.              (- descriptor-low-bits vm:type-bits))
  1213.             (ash (descriptor-low header)
  1214.              (- vm:type-bits)))
  1215.         vm:word-shift))))
  1216.  
  1217. (define-cold-fop (fop-function-entry)
  1218.   (let* ((type (pop-stack))
  1219.      (arglist (pop-stack))
  1220.      (name (pop-stack))
  1221.      (code-object (pop-stack))
  1222.      (offset (calc-offset code-object (read-arg 4)))
  1223.      (fn (descriptor-beyond code-object offset vm:function-pointer-type))
  1224.      (next (read-indexed code-object vm:code-entry-points-slot)))
  1225.     (unless (zerop (logand offset vm:lowtag-mask))
  1226.       (warn "Unaligned function entry: ~S at #x~X" name offset))
  1227.     (write-indexed code-object vm:code-entry-points-slot fn)
  1228.     (write-memory fn (make-other-immediate-descriptor (ash offset
  1229.                                (- vm:word-shift))
  1230.                               vm:function-header-type))
  1231.     (write-indexed fn vm:function-header-self-slot fn)
  1232.     (write-indexed fn vm:function-header-next-slot next)
  1233.     (write-indexed fn vm:function-header-name-slot name)
  1234.     (write-indexed fn vm:function-header-arglist-slot arglist)
  1235.     (write-indexed fn vm:function-header-type-slot type)
  1236.     fn))
  1237.  
  1238. (define-cold-fop (fop-foreign-fixup)
  1239.   (let* ((kind (pop-stack))
  1240.      (code-object (pop-stack))
  1241.      (len (read-arg 1))
  1242.      (sym (make-string len)))
  1243.     (read-n-bytes *fasl-file* sym 0 len)
  1244.     (let ((offset (calc-offset code-object (read-arg 4))))
  1245.       (do-cold-fixup code-object offset (lookup-foreign-symbol sym) kind))
  1246.     code-object))
  1247.  
  1248. (define-cold-fop (fop-assembler-code)
  1249.   (cold-verify-code-format)
  1250.   (let* ((length (read-arg 4))
  1251.      (header-size
  1252.       ;; Note: we round the number of constants up to assure that
  1253.       ;; the code vector will be properly aligned.
  1254.       (round-up vm:code-constants-offset 2))
  1255.      (des (allocate-descriptor *read-only*
  1256.                    (+ (ash header-size vm:word-shift) length)
  1257.                    vm:other-pointer-type)))
  1258.     (write-memory des
  1259.           (make-other-immediate-descriptor header-size
  1260.                            vm:code-header-type))
  1261.     (write-indexed des vm:code-code-size-slot
  1262.            (make-fixnum-descriptor
  1263.             (ash (+ length (1- (ash 1 vm:word-shift)))
  1264.              (- vm:word-shift))))
  1265.     (write-indexed des vm:code-entry-points-slot *nil-descriptor*)
  1266.     (write-indexed des vm:code-debug-info-slot *nil-descriptor*)
  1267.  
  1268.     (read-n-bytes *fasl-file*
  1269.           (descriptor-sap des)
  1270.           (ash header-size vm:word-shift)
  1271.           length)
  1272.     des))
  1273.  
  1274. (define-cold-fop (fop-assembler-routine)
  1275.   (let* ((routine (pop-stack))
  1276.      (des (pop-stack))
  1277.      (offset (calc-offset des (read-arg 4))))
  1278.     (record-cold-assembler-routine
  1279.      routine
  1280.      (+ (logior (ash (descriptor-high des) descriptor-low-bits)
  1281.         (logandc2 (descriptor-low des) vm:lowtag-mask))
  1282.     offset))
  1283.     des))
  1284.  
  1285. (define-cold-fop (fop-assembler-fixup)
  1286.   (let* ((routine (pop-stack))
  1287.      (kind (pop-stack))
  1288.      (code-object (pop-stack))
  1289.      (offset (calc-offset code-object (read-arg 4))))
  1290.     (record-cold-assembler-fixup routine code-object offset kind)
  1291.     code-object))
  1292.  
  1293. ;;; Cold-Load loads stuff into the core image being built by rebinding
  1294. ;;; the Fop-Functions table to a table of cold loading functions.
  1295.  
  1296. (defun cold-load (filename)
  1297.   "Loads the file named by FileName into the cold load image being built."
  1298.   (let* ((*normal-fop-functions* fop-functions)
  1299.      (fop-functions *cold-fop-functions*)
  1300.      (*in-cold-load* t))
  1301.     (with-open-file (file (merge-pathnames
  1302.                filename
  1303.                (make-pathname
  1304.                 :type (c:backend-fasl-file-type c:*backend*)))
  1305.               :element-type '(unsigned-byte 8))
  1306.       (load file :verbose nil))))
  1307.  
  1308.  
  1309.  
  1310. ;;;; Fixups and related stuff.
  1311.  
  1312. (defvar *cold-foreign-symbol-table*
  1313.   (make-hash-table :test 'equal))
  1314.  
  1315. (defun init-foreign-symbol-table ()
  1316.   (clrhash *cold-foreign-symbol-table*))
  1317.  
  1318. (defun load-foreign-symbol-table (filename)
  1319.   (with-open-file (file filename)
  1320.     (let* ((version-line (read-line file))
  1321.        (last-space (position #\Space version-line :from-end t))
  1322.        (version (parse-integer version-line :start (1+ last-space))))
  1323.       (loop
  1324.     (let ((line (read-line file nil nil)))
  1325.       (unless line
  1326.         (return))
  1327.       (let ((value (parse-integer line :end 8 :radix 16))
  1328.         (name (subseq line 11)))
  1329.         (multiple-value-bind
  1330.         (old-value found)
  1331.         (gethash name *cold-foreign-symbol-table*)
  1332.           (when found
  1333.         (warn "Redefining ~S from #x~X to #x~X" name old-value value)))
  1334.         (setf (gethash name *cold-foreign-symbol-table*) value))))
  1335.       version)))
  1336.  
  1337. (defun lookup-foreign-symbol (name)
  1338.   (multiple-value-bind
  1339.       (value found)
  1340.       (gethash name *cold-foreign-symbol-table* 0)
  1341.     (unless found
  1342.       (warn "Undefined foreign symbol: ~S" name))
  1343.     value))
  1344.  
  1345.  
  1346. (defvar *cold-assembler-routines* nil)
  1347.  
  1348. (defvar *cold-assembler-fixups* nil)
  1349.  
  1350. (defun record-cold-assembler-routine (name address)
  1351.   (push (cons name address)
  1352.     *cold-assembler-routines*))
  1353.  
  1354. (defun record-cold-assembler-fixup
  1355.        (routine code-object offset &optional (kind :both))
  1356.   (push (list routine code-object offset kind)
  1357.     *cold-assembler-fixups*))
  1358.  
  1359. (defun lookup-assembler-reference (symbol)
  1360.   (let ((value (cdr (assoc symbol *cold-assembler-routines*))))
  1361.     (unless value (warn "Assembler routine ~S not defined." symbol))
  1362.     value))
  1363.  
  1364. (defun resolve-assembler-fixups ()
  1365.   (dolist (fixup *cold-assembler-fixups*)
  1366.     (let* ((routine (car fixup))
  1367.        (value (lookup-assembler-reference routine)))
  1368.       (when value
  1369.     (do-cold-fixup (second fixup) (third fixup) value (fourth fixup))))))
  1370.  
  1371. (defun do-cold-fixup (code-object offset value kind)
  1372.   (let ((sap (sap+ (descriptor-sap code-object) offset)))
  1373.     (ecase (c:backend-fasl-file-implementation c:*backend*)
  1374.       (#.c:pmax-fasl-file-implementation
  1375.        (ecase kind
  1376.      (:jump
  1377.       (assert (zerop (ash value -26)))
  1378.       (setf (ldb (byte 26 0) (sap-ref-32 sap 0))
  1379.         (ash value -2)))
  1380.      (:lui
  1381.       (setf (sap-ref-16 sap 0)
  1382.         (+ (ash value -16)
  1383.            (if (logbitp 15 value) 1 0))))
  1384.      (:addi
  1385.       (setf (sap-ref-16 sap 0)
  1386.         (ldb (byte 16 0) value)))))
  1387.       (#.c:sparc-fasl-file-implementation
  1388.        (let ((inst (maybe-byte-swap (sap-ref-32 sap 0))))
  1389.      (ecase kind
  1390.        (:call
  1391.         (error "Can't deal with call fixups yet."))
  1392.        (:sethi
  1393.         (setf inst
  1394.           (dpb (ldb (byte 22 10) value)
  1395.                (byte 22 0)
  1396.                inst)))
  1397.        (:add
  1398.         (setf inst
  1399.           (dpb (ldb (byte 10 0) value)
  1400.                (byte 10 0)
  1401.                inst))))
  1402.      (setf (sap-ref-32 sap 0)
  1403.            (maybe-byte-swap inst))))
  1404.       ((#.c:rt-fasl-file-implementation 
  1405.     #.c:rt-afpa-fasl-file-implementation)
  1406.        (ecase kind
  1407.      (:cal
  1408.       (setf (sap-ref-16 sap 2)
  1409.         (maybe-byte-swap-short
  1410.          (ldb (byte 16 0) value))))
  1411.      (:cau
  1412.       (let ((high (ldb (byte 16 16) value)))
  1413.         (setf (sap-ref-16 sap 2)
  1414.           (maybe-byte-swap-short
  1415.            (if (logbitp 15 value) (1+ high) high)))))
  1416.      (:ba
  1417.       (unless (zerop (ash value -24))
  1418.         (warn "#x~8,'0X out of range for branch-absolute." value))
  1419.       (let ((inst (maybe-byte-swap-short (sap-ref-16 sap 0))))
  1420.         (setf (sap-ref-16 sap 0)
  1421.           (maybe-byte-swap-short
  1422.            (dpb (ldb (byte 8 16) value)
  1423.             (byte 8 0)
  1424.             inst))))
  1425.       (setf (sap-ref-16 sap 2)
  1426.         (maybe-byte-swap-short (ldb (byte 16 0) value)))))))))
  1427.  
  1428.  
  1429. (defun linkage-info-to-core ()
  1430.   (let ((result *nil-descriptor*))
  1431.     (maphash #'(lambda (symbol value)
  1432.          (cold-push (allocate-cons *dynamic*
  1433.                        (string-to-core symbol)
  1434.                        (number-to-core value))
  1435.                 result))
  1436.          *cold-foreign-symbol-table*)
  1437.     (cold-setq (cold-intern '*initial-foreign-symbols*) result))
  1438.   (let ((result *nil-descriptor*))
  1439.     (dolist (rtn *cold-assembler-routines*)
  1440.       (cold-push (allocate-cons *dynamic*
  1441.                 (cold-intern (car rtn))
  1442.                 (number-to-core (cdr rtn)))
  1443.          result))
  1444.     (cold-setq (cold-intern '*initial-assembler-routines*) result)))
  1445.  
  1446.  
  1447.  
  1448. ;;;; Emit C Header.
  1449.  
  1450. (defun tail-comp (string tail)
  1451.   (and (>= (length string) (length tail))
  1452.        (string= string tail :start1 (- (length string) (length tail)))))
  1453.  
  1454. (defun head-comp (string head)
  1455.   (and (>= (length string) (length head))
  1456.        (string= string head :end1 (length head))))
  1457.  
  1458. (defun emit-c-header ()
  1459.   (format t "/*~% * Machine generated header file.  Do not edit.~% */~2%")
  1460.   (format t "#ifndef _LISP_H_~%#define _LISP_H_~2%")
  1461.   (format t "#define lowtag_Bits ~D~%" vm:lowtag-bits)
  1462.   (format t "#define lowtag_Mask ((1<<lowtag_Bits)-1)~%")
  1463.   (format t "#define LowtagOf(obj) ((obj)&lowtag_Mask)~%")
  1464.   (format t "#define type_Bits ~D~%" vm:type-bits)
  1465.   (format t "#define type_Mask ((1<<type_Bits)-1)~%")
  1466.   (format t "#define TypeOf(obj) ((obj)&type_Mask)~%")
  1467.   (format t "#define HeaderValue(obj) ((unsigned long) ((obj)>>type_Bits))~2%")
  1468.   (format t "#define Pointerp(obj) ((obj) & 0x01)~%")
  1469.   (format t "#define PTR(obj) ((obj)&~~lowtag_Mask)~2%")
  1470.   (format t "#define fixnum(n) ((n)<<2)~2%")
  1471.   (let ((constants nil))
  1472.     (do-external-symbols (symbol (find-package "VM"))
  1473.       (when (constantp symbol)
  1474.     (let ((name (symbol-name symbol)))
  1475.       (labels
  1476.           ((record (prefix string priority)
  1477.          (push (list (concatenate
  1478.                   'simple-string
  1479.                   prefix
  1480.                   (delete #\- (string-capitalize string)))
  1481.                  priority
  1482.                  (symbol-value symbol)
  1483.                  (documentation symbol 'variable))
  1484.                constants))
  1485.            (test-tail (tail prefix priority)
  1486.          (when (tail-comp name tail)
  1487.            (record prefix
  1488.                (subseq name 0
  1489.                    (- (length name)
  1490.                       (length tail)))
  1491.                priority)))
  1492.            (test-head (head prefix priority)
  1493.          (when (head-comp name head)
  1494.            (record prefix
  1495.                (subseq name (length head))
  1496.                priority))))
  1497.         (test-tail "-TYPE" "type_" 0)
  1498.         (test-tail "-FLAG" "flag_" 1)
  1499.         (test-tail "-TRAP" "trap_" 2)
  1500.         (test-tail "-SUBTYPE" "subtype_" 3)
  1501.         (test-head "TRACE-TABLE-" "tracetab_" 4)))))
  1502.     (setf constants
  1503.       (sort constants
  1504.         #'(lambda (const1 const2)
  1505.             (if (= (second const1) (second const2))
  1506.             (< (third const1) (third const2))
  1507.             (< (second const1) (second const2))))))
  1508.     (let ((prev-priority (second (car constants))))
  1509.       (dolist (const constants)
  1510.     (unless (= prev-priority (second const))
  1511.       (terpri)
  1512.       (setf prev-priority (second const)))
  1513.     (format t "#define ~A ~D~@[  /* ~A */~]~%"
  1514.         (first const) (third const) (fourth const))))
  1515.     (terpri)
  1516.     (format t "#define ERRORS { \\~%")
  1517.     (loop
  1518.       for info across (c:backend-internal-errors c:*backend*)
  1519.       do (format t "    ~S, \\~%" (cdr info)))
  1520.     (format t "    NULL \\~%}~%")
  1521.     (terpri))
  1522.   (let ((structs (sort (copy-list vm:*primitive-objects*) #'string<
  1523.                :key #'(lambda (obj)
  1524.                 (symbol-name (vm:primitive-object-name obj))))))
  1525.     (format t "#ifndef LANGUAGE_ASSEMBLY~2%")
  1526.     (format t "typedef unsigned long lispobj;~%")
  1527.     (format t "#define LISPOBJ(thing) ((lispobj)thing)~2%")
  1528.     (dolist (obj structs)
  1529.       (format t "struct ~A {~%"
  1530.           (nsubstitute #\_ #\-
  1531.                (string-downcase
  1532.                 (string (vm:primitive-object-name obj)))))
  1533.       (when (vm:primitive-object-header obj)
  1534.     (format t "    lispobj header;~%"))
  1535.       (dolist (slot (vm:primitive-object-slots obj))
  1536.     (format t "    ~A ~A~@[[1]~];~%"
  1537.         (getf (vm:slot-options slot) :c-type "lispobj")
  1538.         (nsubstitute #\_ #\-
  1539.                  (string-downcase (string (vm:slot-name slot))))
  1540.         (vm:slot-rest-p slot)))
  1541.       (format t "};~2%"))
  1542.     (format t "#else /* LANGUAGE_ASSEMBLY */~2%")
  1543.     (format t "#define LISPOBJ(thing) thing~2%")
  1544.     (dolist (obj structs)
  1545.       (let ((name (vm:primitive-object-name obj))
  1546.         (lowtag (eval (vm:primitive-object-lowtag obj))))
  1547.     (when lowtag
  1548.       (dolist (slot (vm:primitive-object-slots obj))
  1549.         (format t "#define ~A_~A_OFFSET ~D~%"
  1550.             (substitute #\_ #\- (string name))
  1551.             (substitute #\_ #\- (string (vm:slot-name slot)))
  1552.             (- (* (vm:slot-offset slot) vm:word-bytes) lowtag)))
  1553.       (terpri))))
  1554.     (format t "#endif /* LANGUAGE_ASSEMBLY */~2%"))
  1555.   (dolist (symbol (cons nil vm:exported-static-symbols))
  1556.     (format t "#define ~A LISPOBJ(0x~X)~%"
  1557.         (nsubstitute #\_ #\-
  1558.              (remove-if #'(lambda (char)
  1559.                     (member char '(#\% #\*)))
  1560.                     (symbol-name symbol)))
  1561.         (let ((des (cold-intern symbol)))
  1562.           (logior (ash (descriptor-high des) descriptor-low-bits)
  1563.               (descriptor-low des)))))
  1564.   (terpri)
  1565.   (format t "#endif _LISP_H_~%"))
  1566.  
  1567. ;;; FILES-DIFFER --- internal
  1568. ;;;
  1569. ;;; Return T iff the two files differ.
  1570.  
  1571. (defun files-differ (name1 name2)
  1572.   (if (probe-file name1)
  1573.       (if (probe-file name2)
  1574.       (with-open-file (file1 name1)
  1575.         (with-open-file (file2 name2)
  1576.           (or (null file2)
  1577.           (not (= (file-length file1)
  1578.               (file-length file2)))
  1579.           (do ((line1 "foo" (read-line file1 nil nil))
  1580.                (line2 "foo" (read-line file2 nil nil)))
  1581.               ((and (null line1) (null line2)) nil)
  1582.             (when (or (null line1)
  1583.                   (null line2)
  1584.                   (string/= line1 line2))
  1585.               (return t))))))
  1586.       t)
  1587.       (not (null (probe-file name2)))))
  1588.  
  1589.  
  1590. ;;;; The actual genesis function.
  1591.  
  1592. (defvar *genesis-core-name* "lisp.core")
  1593. (defvar *genesis-map-name* t)
  1594. (defvar *genesis-c-header-name* t)
  1595. (defvar *genesis-symbol-table* nil)
  1596.  
  1597. (defun genesis (file-list &optional
  1598.               (symbol-table *genesis-symbol-table*)
  1599.               (core-name *genesis-core-name*)
  1600.               (map-name *genesis-map-name*)
  1601.               (header-name *genesis-c-header-name*))
  1602.   "Builds a kernel Lisp image from the .FASL files specified in the given
  1603.   File-List and writes it to a file named by Core-Name."
  1604.   (unless symbol-table
  1605.     (error "Can't genesis without a symbol-table."))
  1606.   (format t "~&Building ~S for the ~A~%"
  1607.       core-name (c:backend-version c:*backend*))
  1608.   (setq *current-init-functions-cons* *nil-descriptor*)
  1609.   (let ((*load-time-value-counter* 0)
  1610.     *static* *dynamic* *read-only* *cold-assembler-routines*
  1611.     *cold-assembler-fixups*)
  1612.     (unwind-protect
  1613.     (progn
  1614.       (init-foreign-symbol-table)
  1615.       (let ((version (load-foreign-symbol-table symbol-table)))
  1616.         (initialize-spaces)
  1617.         (initialize-symbols)
  1618.         (dolist (file (if (listp file-list)
  1619.                   file-list
  1620.                   (list file-list)))
  1621.           (let ((file (truename
  1622.                (merge-pathnames file
  1623.                         (make-pathname
  1624.                          :type
  1625.                          (c:backend-fasl-file-type
  1626.                           c:*backend*))))))
  1627.         (write-line (namestring file))
  1628.         (cold-load file))
  1629.           (maybe-gc))
  1630.         (resolve-assembler-fixups)
  1631.         (linkage-info-to-core)
  1632.         (finish-symbols)
  1633.         (finalize-load-time-value-noise)
  1634.         (macrolet
  1635.         ((make-name (name type)
  1636.            `(if (eq ,name t)
  1637.             (make-pathname :type ,type
  1638.                        :defaults core-name)
  1639.             (merge-pathnames ,name
  1640.                      (make-pathname
  1641.                       :defaults core-name
  1642.                       :type ,type)))))
  1643.           (when map-name
  1644.         (with-open-file (*standard-output* (make-name map-name "map")
  1645.                            :direction :output
  1646.                            :if-exists :supersede)
  1647.           (write-map-file)))
  1648.           (when header-name
  1649.         (let* ((name (make-name header-name "h"))
  1650.                (new-name (concatenate 'simple-string
  1651.                           (namestring name) ".NEW"))
  1652.                (won nil))
  1653.           (unwind-protect
  1654.               (progn
  1655.             (with-open-file
  1656.                 (*standard-output* new-name
  1657.                            :direction :output
  1658.                            :if-exists :supersede)
  1659.               (emit-c-header))
  1660.             (unix:unix-chmod (namestring (truename new-name))
  1661.                      #o444)
  1662.             (setf won t))
  1663.             (cond ((and won (files-differ name new-name))
  1664.                (rename-file name
  1665.                     (concatenate 'simple-string
  1666.                              (namestring name)
  1667.                              ".OLD"))
  1668.                (rename-file new-name name)
  1669.                (warn "The C header file has changed.~%Be sure to ~
  1670.                re-compile the startup code and re-run Genesis."))
  1671.               ((delete-file new-name)))))))
  1672.         (write-initial-core-file core-name version)))
  1673.       (dolist (space (list *static* *dynamic* *read-only*))
  1674.     (when space
  1675.       (deallocate-space space))))))
  1676.  
  1677.  
  1678.  
  1679. (defun write-map-file ()
  1680.   (let ((*print-pretty* nil)
  1681.     (*print-case* :upcase))
  1682.     (format t "Assembler routines defined in core image:~%~%")
  1683.     (dolist (routine *cold-assembler-routines*)
  1684.       (format t "~S: #x~X~%" (car routine) (cdr routine)))))
  1685.  
  1686.  
  1687. ;;;; Core file writing magic.
  1688.  
  1689. (defvar *core-file* nil)
  1690. (defvar *data-page* 0)
  1691.  
  1692. (defparameter version-entry-type-code 3860)
  1693. (defparameter validate-entry-type-code 3845)
  1694. (defparameter directory-entry-type-code 3841)
  1695. (defparameter new-directory-entry-type-code 3861)
  1696. (defparameter end-entry-type-code 3840)
  1697.  
  1698. (defun write-long (num)
  1699.   (ecase (c:backend-byte-order c:*backend*)
  1700.     (:little-endian
  1701.      (dotimes (i 4)
  1702.        (write-byte (ldb (byte 8 (* i 8)) num) *core-file*)))
  1703.     (:big-endian
  1704.      (dotimes (i 4)
  1705.        (write-byte (ldb (byte 8 (* (- 3 i) 8)) num) *core-file*)))))
  1706.  
  1707.  
  1708. (defun advance-to-page ()
  1709.   (force-output *core-file*)
  1710.   (file-position *core-file*
  1711.          (round-up (file-position *core-file*)
  1712.                *target-page-size*)))
  1713.  
  1714. (defun output-space (space)
  1715.   (force-output *core-file*)
  1716.   (let* ((posn (file-position *core-file*))
  1717.      (bytes (* (space-free-pointer space) vm:word-bytes))
  1718.      (pages (ceiling bytes *target-page-size*))
  1719.      (total-bytes (* pages *target-page-size*)))
  1720.     ;; 
  1721.     (file-position *core-file* (* *target-page-size* (1+ *data-page*)))
  1722.     (format t "Writing ~S byte~:P [~S page~:P] from ~S space~%"
  1723.         total-bytes pages (space-name space))
  1724.     (force-output)
  1725.     ;;
  1726.     ;; Note: It is assumed that the space allocation routines always
  1727.     ;; allocate whole pages (of size *target-page-size*) and that any empty
  1728.     ;; space between the free pointer and the end of page will be
  1729.     ;; zero-filled.  This will always be true under Mach on machines
  1730.     ;; where the page size is equal.  (RT is 4K, PMAX is 4K, Sun 3 is 8K).
  1731.     ;; 
  1732.     (system:output-raw-bytes *core-file* (space-sap space) 0 total-bytes)
  1733.     (force-output *core-file*)
  1734.     (file-position *core-file* posn)
  1735.     ;; 
  1736.     ;; Write part of a (new) directory entry which looks like this:
  1737.     ;;
  1738.     ;; SPACE IDENTIFIER
  1739.     ;; WORD COUNT
  1740.     ;; DATA PAGE
  1741.     ;; ADDRESS
  1742.     ;; PAGE COUNT
  1743.     ;; 
  1744.     (write-long (space-identifier space))
  1745.     (write-long (space-free-pointer space))
  1746.     (write-long *data-page*)
  1747.     (write-long (/ (ash (space-address space) vm:word-shift)
  1748.            *target-page-size*))
  1749.     (write-long pages)
  1750.     (incf *data-page* pages)))
  1751.  
  1752. (defun write-initial-core-file (name version)
  1753.   (format t "[Building Initial Core File (version ~D) in file ~S: ~%"
  1754.       version (namestring name))
  1755.   (force-output)
  1756.   (let ((*data-page* 0))
  1757.     (with-open-file (*core-file* name
  1758.                  :direction :output
  1759.                  :element-type '(unsigned-byte 8)
  1760.                  :if-exists :rename-and-delete)
  1761.       ;; Write the magic number
  1762.       ;; 
  1763.       (write-long (logior (ash (char-code #\C) 24)
  1764.               (ash (char-code #\O) 16)
  1765.               (ash (char-code #\R) 8)
  1766.               (char-code #\E)))
  1767.       
  1768.       ;; Write the Version entry.
  1769.       ;; 
  1770.       (write-long version-entry-type-code)
  1771.       (write-long 3)
  1772.       (write-long version)
  1773.  
  1774.       ;; Write the New Directory entry header.
  1775.       ;; 
  1776.       (write-long new-directory-entry-type-code)
  1777.       (write-long 17) ; length = 5 words / space * 3 spaces + 2 for header.
  1778.       
  1779.       (output-space *read-only*)
  1780.       (output-space *static*)
  1781.       (output-space *dynamic*)
  1782.       
  1783.       ;; Write the End entry.
  1784.       ;; 
  1785.       (write-long end-entry-type-code)
  1786.       (write-long 2)))
  1787.   (format t "done]~%")
  1788.   (force-output))
  1789.  
  1790.